package com.foreveross.proxyip.core.pools.thread;

import com.foreveross.proxyip.core.pools.AvailablePool;
import com.foreveross.proxyip.core.redis.RedisLock;
import com.foreveross.proxyip.core.redis.RedisManager;
import com.foreveross.proxyip.core.zk.ZkAppCenter;
import com.foreveross.proxyip.core.zk.ZkPlan;
import com.foreveross.proxyip.core.zk.task.strategy.CheckInTask;

public abstract class AbsCheckInThread extends CircleThread {

	protected String doloadSourceTask = "";

	public AbsCheckInThread(AvailablePool pool, CheckType checkType) throws Exception {
		super(pool, checkType);
		super.setIsInit(true);
	}

	/**
	 * 如果池正在执行checkOut，返回false不能执行checkin
	 */

	public String getName() {
		return "检入";
	}

	/**
	 * 检入完成，因为是异步检入，所以线程池在循环中随时都可能初始化完成
	 * 
	 * @throws Exception
	 */
	@Override
	public void executeFinish() throws Exception {
		if (isInit) {
			// 当初始化公共池已经充满代理ip，检测线程正常工作阶段，执行沉睡
			if (pool.size() >= pool.getProxyMin()) {
				isInit = false;
			}
		}
	}

	@Override
	public boolean needSleep() throws Exception {
		return this.pool.size() >= this.pool.getProxyMax();
	}

	/**
	 * 把检入任务的ip放到队列CheckInTask.getSourceKey(this.pool);
	 * 
	 * @param currSize
	 * @return true 表示此次checkIn有效
	 * 
	 * @throws Exception
	 */
	public boolean loadSourceIps(Long currSize) throws Exception {
		Long num = getNeedSize(currSize);
		
		// 如果池己满，但待验证的队列中还数据，则进行一次验证
		if (num == 0) {
			return getSourceSize() > 0;
		}
		
		// 1.5倍任务量。
		ZkPlan plan = new ZkPlan(this.pool.poolSign, "DoloadTask", num , this.pool.sourceNum, ZkAppCenter.getInstance());
		plan.executeWait();// 这个方法会等到所有任务都执行r完毕。

		log.info("{}_source:{}" , this.pool.poolSign , RedisManager.getInstance().len(CheckInTask.getSourceKey(this.pool)));

		return true;
	}

/*	protected Long getNeedSize(Long currSize) throws Exception {
		Long num = pool.getProxyMax() - currSize;// 应用的最大值*应用的数量
		
		if (num <= 0) {
			num = 0L;
			return num;
		}
		
		Long sourceLen = getSourceSize();
		
		sourceLen = sourceLen == null ? 0L : sourceLen;// 下载源已经有的数量了。
		
		if (num * 12 / 10 >= sourceLen) {
			num = num * 12 / 10 - sourceLen;
		} else {
			return 0L;
		}

		return num;
	}*/
	
	protected Long getNeedSize(Long currSize) throws Exception {
		Long needNum = pool.getProxyMax() - currSize;// 应用的最大值*应用的数量
		Long sourceLen = getSourceSize();
		sourceLen = sourceLen == null ? 0L : sourceLen;// 下载源已经有的数量了。
		needNum -= sourceLen;
		
		if (needNum <= 0) {
			needNum = 0L;
			return needNum;
		}
		
		return needNum < 0 ? 0L : needNum;
	}

	@Override
	public void publishTask() throws Exception {
		RedisLock lock = new RedisLock(this.pool.poolSign + "_CheckInTasklock");// 需要加锁，不能并行。
		
		// 如果上锁成功，则执行下面操作否则放弃此次操作
		if (!lock.tryLock()) {
			return;
		}
		
		try {
			
			Long currSize = this.pool.size();
			currSize = currSize == null ? 0L : currSize;
			
			log.info("pool:{}, PoolProxyMin:{}, currSize:{}", pool.poolSign, pool.getProxyMin(), currSize);
			
			if (pool.getProxyMin() <= currSize) {
				return;
			}
			
			log.info(this.pool.poolSign+" checkIn");
			
			Long begin = System.currentTimeMillis();
			
			if (this.loadSourceIps(currSize)) {
				log.debug(this.pool.poolSign + " loadSourceIps spend times :" + (System.currentTimeMillis() - begin));
				begin = System.currentTimeMillis();
				ZkPlan plan = new ZkPlan(this.pool.poolSign, "CheckInTask", getSourceSize(), this.pool.sourceNum, ZkAppCenter.getInstance());
				plan.execute();
				log.debug(this.pool.poolSign + " expire time execute publishTask times :" + (System.currentTimeMillis() - begin));
			}
		} finally {
			lock.unlock();
		}

	}

	/**
	 * 渠道池会改变
	 * 
	 * @return
	 */
	protected Long getSourceSize() throws Exception {
		return RedisManager.getInstance().len(CheckInTask.getSourceKey(pool));
	}

}
